<html>
	<title>nTube: Embed</title>
	<head>
		<style>
			#overlay {
  				position: fixed; /* Sit on top of the page content */
  				/*display: none; /* Hidden by default */ 
  				width: 100%; /* Full width (cover the whole page) */
  				height: 100%; /* Full height (cover the whole page) */
  				top: 0;
  				left: 0;
  				right: 0;
  				bottom: 0;
  				background-color: rgba(0,0,0,0.5); /* Black background with opacity */
  				z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
  				cursor: pointer; /* Add a pointer on hover */
			}
			#text{
  				position: absolute;
  				top: 50%;
  				left: 50%;
  				font-size: 24px;
  				color: white;
  				transform: translate(-50%,-50%);
  				-ms-transform: translate(-50%,-50%);
			}
		</style>
		<script type="text/javascript" >
		var desyncHandle = 5;		
		
		function syncPlayers(mainPlayer, audioPlayer) {
			mainPlayer.pause();
			audioPlayer.pause();
	
			var ready = false;
			audioPlayer.addEventListener("canplay", function () {
				ready = true;
				mainPlayer.play();
			});
			mainPlayer.addEventListener("canplay", function () {
				if (ready) {
					audioPlayer.play();		
					ready = true;
				}
			});
			mainPlayer.addEventListener("play", function() {
				audioPlayer.play();	
				syncVideos(ready, mainPlayer, audioPlayer);
			});
			mainPlayer.addEventListener("pause", function () {
				audioPlayer.pause();
				syncVideos(ready, mainPlayer, audioPlayer);
			});
			mainPlayer.addEventListener("timeupdate", function () {
				syncVideos(ready, mainPlayer, audioPlayer);
			});
			audioPlayer.addEventListener("timeupdate", function () {
				//syncVideos(ready, audioPlayer, mainPlayer);
				syncVideos(ready, mainPlayer, audioPlayer);
			});
			mainPlayer.addEventListener("seeking", function () {
				syncVideos(ready, mainPlayer, audioPlayer);
				if (desyncHandle != 5) {
					audioPlayer.pause();		
				}
			});
			mainPlayer.addEventListener("seeked", function () {
				audioPlayer.play();
				syncVideos(ready, mainPlayer, audioPlayer);
			});
			audioPlayer.addEventListener("seeking", function () {
				syncVideos(ready, mainPlayer, audioPlayer);
				if (desyncHandle != -5) {
					mainPlayer.pause();		
				}
			});
			audioPlayer.addEventListener("seeked", function () {
				mainPlayer.play();
				syncVideos(ready, mainPlayer, audioPlayer);
			});
	}		

	function syncVideos0(ready, mainPlayer, audioPlayer) {
		if (ready) {
			if (audioPlayer.currentTime - mainPlayer.currentTime >= 0.6 ||
		 		audioPlayer.currentTime - mainPlayer.currentTime <= -0.6) {
				audioPlayer.currentTime = mainPlayer.currentTime;		
			}
		}
	}

function syncVideos1(ready, mainPlayer, audioPlayer) {
	if (ready) {
		if (audioPlayer.currentTime - mainPlayer.currentTime >= 1 ||
		 audioPlayer.currentTime - mainPlayer.currentTime <= -1) {
			audioPlayer.currentTime = mainPlayer.currentTime;		
		}
	}
}

function syncVideos2(ready, mainPlayer, audioPlayer) {
	if (ready) {
		if (audioPlayer.currentTime - mainPlayer.currentTime >= 500 ||
		 audioPlayer.currentTime - mainPlayer.currentTime <= -500) {
			audioPlayer.currentTime = mainPlayer.currentTime;		
		}
	}
}

function syncVideos3(ready, mainPlayer, audioPlayer) {
	if (ready) {
		if (audioPlayer.currentTime - mainPlayer.currentTime >= 0.45 ||
		 audioPlayer.currentTime - mainPlayer.currentTime <= -0.45) {
			audioPlayer.currentTime = mainPlayer.currentTime;		
		}
	}
}

function syncVideosPerfect(ready, mainPlayer, audioPlayer) {
	if (ready) {
		//audioPlayer.currentTime = mainPlayer.currentTime;
		// previous values: 0.1, -0.1
		if (audioPlayer.currentTime - mainPlayer.currentTime >= 0.12 ||
		 audioPlayer.currentTime - mainPlayer.currentTime <= -0.12) {
			audioPlayer.currentTime = mainPlayer.currentTime;		
		}
	}
}

function syncVideosLite(ready, mainPlayer, audioPlayer) {
	if (ready) {
		//audioPlayer.currentTime = mainPlayer.currentTime;
		// previous values: 0.1, -0.1
		if (audioPlayer.currentTime - mainPlayer.currentTime >= 0.22 ||
		 audioPlayer.currentTime - mainPlayer.currentTime <= -0.22) {
			audioPlayer.currentTime = mainPlayer.currentTime;		
		}
	}
}

function syncVideos(ready, mainPlayer, audioPlayer) {
	if (desyncHandle == -1) {
		return;	
	}
	if (desyncHandle == 0) {
		syncVideos0(ready, mainPlayer, audioPlayer);
	}else if (desyncHandle == 1) {
		syncVideos1(ready, mainPlayer, audioPlayer);
	}else if (desyncHandle == 2) {
		syncVideos2(ready, mainPlayer, audioPlayer);	
	}else if (desyncHandle == 3) {
		syncVideos3(ready, mainPlayer, audioPlayer);	
	}else if (desyncHandle == 5) {
		syncVideosPerfect(ready, mainPlayer, audioPlayer);
	}else if (desyncHandle == 6) {
		syncVideosLite(ready, mainPlayer, audioPlayer);
	}else {
		syncVideos0(ready, mainPlayer, audioPlayer);
	}	
}

function send_request(url, data, onFail, onSuccess) {
	if (typeof fetch != "undefined") {
		fetch(url).then(function(response) {
    		return response.text();
   	}).then(function(json) {
   		onSuccess(json);
   	}).catch(function(ex) {
   		console.error(ex);
   		console.error("Exception URL: " + url);
    		onFail();
  		});	
	}else {
		console.warn("send_request() -> Outdated browser found, attempting fallback method...");
		var http = null;
		if (window.XMLHttpRequest) {
			http = new XMLHttpRequest();		
		}else {
			http = new ActiveXObject("Microsoft.XMLHTTP");
		}
		http.open('POST', url, true);
	   http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
	   
	   var hasResponse = false;
	   //var res = "";
	   http.onreadystatechange = function() {
		if (http.readyState == 4 && http.status == 200) {
		//		res = http.responseText;
				var sp = http.responseText.split("\n");
				onSuccess(sp[sp.length - 1]);
			}
		}
		http.ontimeout = function() {
			alert("nTube: onTimeout() was called when fetching your video!");
		}
		http.send(params);
	}
	//var http = new XMLHttpRequest();
	//var params = data;
	//http.timeout = 0;
	//http.responseType = 'blob';
	//http.open('POST', url, true);
	//http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
			
	//var hasResponse = false;
	//var res = "";
	//http.onreadystatechange = function() {
	//	if (http.readyState == 4 && http.status == 200) {
	//		res = http.responseText;
	//		onSuccess(http.responseText);
	//	}
	//}
	//http.ontimeout = function() {
	//	alert("nTube: onTimeout() was called when fetching your video!");
	//}
	//http.send(params);
	
	/*		
	var stop = false;
	var time = 0;
	while (!hasResponse) {
		if (stop) {
			break;
		}
		if (time > 1500) {
			//alert("Timeout occured, try again.");
			onFail();
			stop = true;
		}
		var ix = -1;
		time += 1;
	}*/
}
		</script>
		<style type="text/css">
.wrapper {
  position: absolute;
  width: 400px;
  height: 2px;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  margin: auto;
}

.loader {
  height: 100%;
  display: flex;
  -webkit-transform: translateZ(0);
          transform: translateZ(0);
}
.loader div {
  flex: 1;
  background: salmon;
  -webkit-animation: go 0.8s infinite alternate ease;
          animation: go 0.8s infinite alternate ease;
  box-shadow: 0 0 20px salmon;
}
.loader div:nth-child(1) {
  -webkit-animation-delay: -0.72s;
          animation-delay: -0.72s;
}
.loader div:nth-child(2) {
  -webkit-animation-delay: -0.64s;
          animation-delay: -0.64s;
}
.loader div:nth-child(3) {
  -webkit-animation-delay: -0.56s;
          animation-delay: -0.56s;
}
.loader div:nth-child(4) {
  -webkit-animation-delay: -0.48s;
          animation-delay: -0.48s;
}
.loader div:nth-child(5) {
  -webkit-animation-delay: -0.4s;
          animation-delay: -0.4s;
}
.loader div:nth-child(6) {
  -webkit-animation-delay: -0.32s;
          animation-delay: -0.32s;
}
.loader div:nth-child(7) {
  -webkit-animation-delay: -0.24s;
          animation-delay: -0.24s;
}
.loader div:nth-child(8) {
  -webkit-animation-delay: -0.16s;
          animation-delay: -0.16s;
}
.loader div:nth-child(9) {
  -webkit-animation-delay: -0.08s;
          animation-delay: -0.08s;
}
.loader div:nth-child(10) {
  -webkit-animation-delay: 0s;
          animation-delay: 0s;
}

@-webkit-keyframes go {
  100% {
    background: transparent;
    flex: 10;
    box-shadow: 0 0 0 transparent;
  }
}

@keyframes go {
  100% {
    background: transparent;
    flex: 10;
    box-shadow: 0 0 0 transparent;
  }
}
		</style>
		<style type="text/css">
			html {
				background-color: black;
				color: white;
				font-family: sans-serif;			
			}
		</style>
	</head>
	<body>
		<div>
			<div id="overlay">
				<div id="text">Press ANYWHERE to begin watching.</div>
			</div>
			<script type="text/javascript" >
			function hide(object) {
				object.style.display = "none";
				object.style.visibility = "none";
			}

			function init() {
				var URL = document.URL;
				var videoID = URL.split("\?")[1];
				send_request("/get_embed?" + videoID, "", function() {
					document.getElementById("_text").innerHTML = "Failed to connect to nTube's API.";
				}, function (data) {
					var object = JSON.parse(data);
					document.getElementById("_text").innerHTML = object.videoTitle;
					var mainPlayer = document.getElementById("_video");
					mainPlayer.poster = object.videoThumbnail;
					document.getElementById("_url").href = object.wurl;
					if (object.newCaptions) {
						var mainPl = mainPlayer;
						var i = 0;
						var obj;
						for (; i < object.newCaptions.length; i++) {
							obj = object.newCaptions[i];
							var track = document.createElement("track");
							track.kind = "captions";
   							track.label = obj.cn
   							track.srclang = obj.cc;
   							track.src = "/b64_dec?td=" + obj.webVTT;
							mainPl.appendChild(track);
						}						
					}
					if (object.video60 && object.videoA) {
						hide(document.getElementById("nplayer_loading"));
						mainPlayer.src = object.video60;
						document.getElementById("_audio").src = object.videoA;
						syncPlayers(mainPlayer, document.getElementById("_audio"));
						mainPlayer.controls = true;
					} else if (object.videoURL && !object.live) {
						hide(document.getElementById("nplayer_loading"));
						mainPlayer.src = object.videoURL;
						mainPlayer.controls = true;
					} else if (object.videoURL && object.live) {
						hide(document.getElementById("nplayer_loading"));
						mainPlayer.controls = true;
						console.log("[nTube] [Player.API] Using hls.js to provide stream support...");
						var script = document.createElement('script');
						script.setAttribute("crossorigin", "true");
						script.onload = function () {
							//var video = document.getElementById("__player");
							if (mainPlayer.canPlayType('application/vnd.apple.mpegurl')) {
								mainPlayer.src = object.videoURL;
								mainPlayer.addEventListener('loadedmetadata',function() {
									mainPlayer.play();
    							});
							}else if (Hls.isSupported()) {
								var hls = new Hls();
								hls.on(Hls.Events.ERROR, function (event, data) {
    								var errorType = data.type;
    								var errorDetails = data.details;
    								var errorFatal = data.fatal;
    								console.error("[nTube] [Player.API] " + errorDetails + " [Type=" + errorType + ",fatal=" + errorFatal + "]");
    								if (errorFatal) {
										//var errDiv = document.getElementById("_vid_error");		
										//errDiv.style.display = "";
										//errDiv.style.visibility = "";
										if (errorDetails == "manifestLoadError") {
											//document.getElementById("_vid_error_text").innerHTML = "Couldn't connect to servers, probably CORS. Check your console.";
											mainPlayer.src = object.videoURL;													
										}else {
											//document.getElementById("_vid_error_text").innerHTML = errorDetails;
										}    											
    								}
    							});
								hls.loadSource(object.videoURL);
    							hls.attachMedia(mainPlayer);
    							hls.on(Hls.Events.MANIFEST_PARSED,function() {
    								mainPlayer.play();
    							});
							}else {
								mainPlayer.src = object.videoURL;
							}
						}
						script.src = "https://cdn.jsdelivr.net/npm/hls.js@latest";
						document.head.appendChild(script);
					
					} else {
						hide(document.getElementById("nplayer_loading"));
						document.getElementById("_text").innerHTML = "ERROR: No video data detected";
					}
				});
			}	
			//init(); Don't do that, I may send TOO MANY REQUESTS to YouTube (i.e. 6 * 3 = 18 requests in a span of 15 seconds is BAD.)
			document.getElementById("overlay").onclick = function() {
				document.getElementById("overlay").style.display = "none";
				document.getElementById("overlay").style.visibility = "hidden";
				init();
			};
			</script>
			<video id="_video" autoplay="autoplay" style="height: 90%;width: 100%;"></video>
			<div class="wrapper" id="nplayer_loading">
  				<div class="loader">
   				<div></div>
    				<div></div>
    				<div></div>
    				<div></div>
    				<div></div>
    				<div></div>
    				<div></div>
    				<div></div>
    				<div></div>
  				</div>
			</div>
			<video id="_audio" src="" autoplay="autoplay" controls="false" style="display: none; visibility: hidden;"></video>
			<h4 id="_text" style="line-height: 90%;">Loading...</h4>
			<div>
				<p style="font-size: x-small;float: left;line-height: 1%;"><span style="color: red;">n</span><span style="color: lightgreen;">Tube</span> Embedded 1.0.0</p>
				<a id="_url" href="" style="text-decoration: underline dotted gray; color: white;float: right;line-height: 40%;">Watch on <span style="color: red;">n</span><span style="color: lightgreen;">Tube</span></a>			
				<div style="clear: both;"></div>
				<p style="font-size: x-small">You are watching this in complete privacy.</p>
			</div>
		</div>
	</body>
</html>
